<?php

namespace stlswm\JsonObject;

use \Exception;

/**
 * Class Json
 *
 * @package stlswm\JsonObject
 */
class Json
{
    /**
     * 解析数据到对象
     *
     * @param ClassMap $classMap
     * @param          $decode
     *
     * @throws Exception
     */
    private static function parseToObject(ClassMap &$classMap, $decode)
    {
        foreach ($decode as $key => $value) {
            if (is_object($value)) {
                if (!property_exists($classMap, $key) || !$classMap->$key instanceof ClassMap) {
                    $classMap->$key = new ClassMap();
                }
                self::parseToObject($classMap->$key, $value);
            } else {
                if (is_array($value) && isset($classMap->getClassMap()[$key])) {
                    $itemClassName = $classMap->getClassMap()[$key];
                    $classMap->$key = [];
                    foreach ($value as $valueItem) {
                        $itemClass = new $itemClassName;
                        self::parseToObject($itemClass, $valueItem);
                        $classMap->$key[] = $itemClass;
                    }
                } else {
                    $classMap->$key = $value;
                }
            }
        }
    }

    /**
     * @param     $value
     * @param int $options
     * @param int $depth
     *
     * @return false|string
     */
    public static function marshal($value, int $options = 0, int $depth = 512)
    {
        return json_encode($value, $options, $depth);
    }

    /**
     * 解析json字符串到对象中
     *
     * @param string   $json
     * @param ClassMap $class
     * @param int      $depth
     * @param int      $options
     *
     * @return bool
     * @throws Exception
     */
    public static function unMarshal(string $json, ClassMap &$class, int $depth = 512, int $options = 0): bool
    {
        $decode = json_decode($json, FALSE, $depth, $options);
        if (!$decode) {
            return FALSE;
        }
        self::parseToObject($class, $decode);
        return TRUE;
    }
}